#include <jni.h>
#include <string>
#include "macro.h"
#include "VideoChannel.h"

VideoChannel *videoChannel = 0;

#include "safe_queue.h"
#include "AudioChannel.h"

int isStart = 0;
pthread_t pid;
int readyPushing = 0;
SafeQueue<RTMPPacket *> packets;
uint32_t start_time;

AudioChannel *audioChannel = 0;

void releasePackets(RTMPPacket *&packet) {
    if (packet) {
        RTMPPacket_Free(packet);
        delete packet;
        packet = 0;
    }
}


void callback(RTMPPacket *packet) {
    if (packet) {
        packet->m_nTimeStamp = RTMP_GetTime() - start_time;
        //把数据放到集合中
        packets.push(packet);
    }
}

void *start(void *args) {

    char *url = static_cast<char *>(args);
    RTMP *rtmp = 0;
    do {

        rtmp = RTMP_Alloc();
        if (!rtmp) {
            LOGE("rtmp创建失败");
            break;
        }
        RTMP_Init(rtmp);
        //设置超时时间是5秒
        rtmp->Link.timeout = 5;
        int ret = RTMP_SetupURL(rtmp, url);

        if (!ret) {
            LOGE("rtmp的地址失败%s", url);
            break;
        }
        RTMP_EnableWrite(rtmp);
        ret = RTMP_Connect(rtmp, 0);
        if (!ret) {
            LOGE("rtmp连接地址失败:%s", url);
            break;
        }
        ret = RTMP_ConnectStream(rtmp, 0);
        if (!ret) {
            LOGE("rtmp连接流失败:%s", url);
            break;
        }

        //准备好了 可以开始推流了
        readyPushing = 1;
        start_time = RTMP_GetTime();

        packets.setWork(1);
        RTMPPacket *packet = 0;
        //保证第一个数据是 aac解码数据包
        callback(audioChannel->getAudioTag());
        //从队列中取包
        while (isStart) {
            //没有数据会阻塞
            packets.pop(packet);

            if (!isStart) {
                break;
            }
            if (!packet) {
                continue;
            }
            //发送数据
            // 给rtmp的流id
            packet->m_nInfoField2 = rtmp->m_stream_id;
            ret = RTMP_SendPacket(rtmp, packet, 1);
            releasePackets(packet);
            if (!ret) {
                LOGE("发送数据失败");
                break;
            }
        }

        releasePackets(packet);

    } while (0);


    if (rtmp) {
        RTMP_Close(rtmp);
        RTMP_Free(rtmp);
    }
    delete url;
    return 0;
}


extern "C" JNIEXPORT jstring JNICALL
Java_com_example_pushapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";


    RTMP_GetTime();

    new x264_level_t;
    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_pushapplication_live_LivePusher_native_1start(JNIEnv *env, jobject instance,
                                                               jstring path_) {


    //传递要播放的地址

    if (isStart) {
        return;
    }
    //开始链接服务
    const char *path = env->GetStringUTFChars(path_, 0);
    char *url = new char[strlen(path) + 1];
    strcpy(url, path);
    isStart = 1;
    //启动一个线程去连接
    pthread_create(&pid, 0, start, url);

    env->ReleaseStringUTFChars(path_, path);
}


extern "C"
JNIEXPORT void JNICALL
Java_com_example_pushapplication_live_LivePusher_native_1init(JNIEnv *env, jobject instance) {

    //初始化播放器
    videoChannel = new VideoChannel;
    //把视频数据 到集合中
    videoChannel->setVideoCallback(callback);


    audioChannel = new AudioChannel;
    //数据的回调
    audioChannel->setAudioCallback(callback);
    //释放数据
    packets.setReleaseCallback(releasePackets);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_pushapplication_live_LivePusher_native_1setVideoEncInfo(JNIEnv *env,
                                                                         jobject instance,
                                                                         jint width, jint height,
                                                                         jint fps, jint bitrate) {

    // 初始化编码器
    if (videoChannel) {
        videoChannel->setVideoEncInfo(width, height, fps, bitrate);
    }


}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_pushapplication_live_LivePusher_native_1pushVideo(JNIEnv *env, jobject instance,
                                                                   jbyteArray data_) {

    if (!videoChannel || !readyPushing) {
        return;
    }
    jbyte *data = env->GetByteArrayElements(data_, NULL);
    //发送数据
    videoChannel->encodeData(data);
    env->ReleaseByteArrayElements(data_, data, 0);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_pushapplication_live_LivePusher_getInputSamples(JNIEnv *env, jobject thiz) {
     if (audioChannel){
         return  audioChannel->getInputSamples();
     }

}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_pushapplication_live_LivePusher_native_1pushAudio(JNIEnv *env, jobject thiz,
                                                                   jbyteArray bytes) {
    //开始编码
    if (!audioChannel || !readyPushing){
        return;
    }
    jbyte *data =  env->GetByteArrayElements(bytes,NULL);
    audioChannel->encodeData(data);
    env->ReleaseByteArrayElements(bytes,data,0);

}extern "C"
JNIEXPORT void JNICALL
Java_com_example_pushapplication_live_LivePusher_native_1setAudioEncInfo(JNIEnv *env, jobject thiz,
                                                                         jint sample_rate_in_hz,
                                                                         jint channels) {
    if (audioChannel) {
        audioChannel->setAudioEncInfo(sample_rate_in_hz, channels);
    }

}